from sklearn.datasets import load_breast_cancer  # 导入示例数据集（未在函数中使用）
from sklearn.ensemble import IsolationForest  # 孤立森林模型用于异常检测
from sklearn.preprocessing import StandardScaler  # 数据标准化工具
import pandas as pd  # 数据处理库
import numpy as np  # 数值计算库
import matplotlib.pyplot as plt  # 绘图库
from matplotlib import rcParams  # 设置绘图参数

# 设置字体为SimHei（黑体），解决matplotlib中文显示问题
rcParams['font.sans-serif'] = ['SimHei']
rcParams['axes.unicode_minus'] = False  # 解决负号显示问题


def outlier_detection(xlsx_file, feature1,feature2,select_feature, output_file="outlier_detection.png"):
    """
    异常点检测函数。

    参数：
    - xlsx_file: 数据文件路径，支持.xlsx文件。
    - select_feature: 要分析的目标列名称列表。
    - output_file: 输出图像文件路径，默认为"outlier_detection.png"。
    """
    # 加载数据集
    df = pd.read_excel(xlsx_file)  # 读取xlsx文件

    # 根据输入选择特征
    X = df[select_feature]

    # 数据标准化，因为IsolationForest对特征分布较为敏感
    scaler = StandardScaler()
    X_scaled = scaler.fit_transform(X)

    # 设置孤立森林模型参数
    clf = IsolationForest(contamination=0.1, random_state=42)  # contamination表示估计的异常比例
    clf.fit(X_scaled)  # 训练模型

    # 预测异常点：1 表示正常，-1 表示异常
    predictions = clf.predict(X_scaled)
    df['anomaly'] = predictions  # 将预测结果添加到DataFrame中

    # 统计并打印异常点信息
    anomalies_indices = [index for index, value in enumerate(df['anomaly']) if value == -1]
    for ai in anomalies_indices:
        print(f"有异常的数据位于{ai}行")
    print("异常点数量:", len(anomalies_indices))
    print("正常点数量:", (df['anomaly'] == 1).sum())

    # 生成列表 -1表示异常点，1表示正常
    results = [[row[feature1],
                row[feature2],
                row['anomaly']] for _, row in df.iterrows()]

    # 可视化部分特征
    feature_1 = feature1
    feature_2 = feature2

    plt.figure(figsize=(10, 6))  # 创建图形
    plt.scatter(df[feature_1][df['anomaly'] == 1], df[feature_2][df['anomaly'] == 1],
                label="正常点", alpha=0.6)  # 正常点散点图
    plt.scatter(df[feature_1][df['anomaly'] == -1], df[feature_2][df['anomaly'] == -1],
                label="异常点", color="red", alpha=0.8)  # 异常点散点图
    plt.xlabel(feature_1)
    plt.ylabel(feature_2)
    plt.title("异常点检测可视化")
    plt.legend()  # 显示图例
    plt.show()  # 展示图像
    plt.savefig(output_file)  # 保存图像
    print(f"散点图已保存为: {output_file}")
    print(results)


# 调用函数，传入参数
outlier_detection("抗压强度_修改后.xlsx","7d抗压（MPa）","28d抗压（MPa）",
                  ["水用量（kg/m3）", "水泥ID", "水泥用量（kg/m3）",
                   "粉煤灰用量（kg/m3）", "砂ID", "砂用量（kg/m3）",
                   "石ID", "石用量（kg/m3）", "减水剂ID",
                   "减水剂掺量（%）", "增效剂ID", "增效剂掺量（%）"])
